package com.hkyp.ss.course.provider.impl;

import com.hkyp.ss.course.apis.CourseBackService;
import com.hkyp.ss.course.apis.dto.common.PageReq;
import com.hkyp.ss.course.apis.dto.common.PageResp;
import com.hkyp.ss.course.apis.dto.query.CourseSpecification;
import com.hkyp.ss.course.apis.dto.request.CourseDTO;
import com.hkyp.ss.course.apis.dto.request.HomePageCourseDTO;
import com.hkyp.ss.course.apis.dto.response.CourseBackVO;
import com.hkyp.ss.course.apis.enumu.CourseStatusEnum;
import com.hkyp.ss.course.apis.enumu.DeletedEnum;
import com.hkyp.ss.course.apis.enumu.YesNoEnum;
import com.hkyp.ss.course.apis.exception.BusinessException;
import com.hkyp.ss.course.apis.exception.UnacceptableException;
import com.hkyp.ss.course.apis.utils.BeanMapper;
import com.hkyp.ss.course.apis.utils.NumberGeneratorUtil;
import com.hkyp.ss.course.provider.model.Course;
import com.hkyp.ss.course.provider.model.NavigationItem;
import com.hkyp.ss.course.provider.repository.CourseRepository;
import com.hkyp.ss.course.provider.repository.NaviItemRepository;
import com.hkyp.ss.course.provider.repository.mediate.UserCourCollRepository;
import com.hkyp.ss.course.provider.repository.mediate.UserCourLikeRepository;
import lombok.extern.slf4j.Slf4j;
import org.apache.dubbo.config.annotation.Service;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

import java.util.*;
import java.util.stream.Collectors;
import java.util.stream.Stream;

@Slf4j
@Service(version = "1.0")
@Transactional(rollbackFor = Exception.class)
public class CourseBackServiceImpl implements CourseBackService {


    @Autowired
    CourseRepository courseRepository;
    @Autowired
    UserCourLikeRepository userCourLikeRepository;

    @Autowired
    UserCourCollRepository userCourCollRepository;

    @Autowired
    private NaviItemRepository naviItemRepository;


    @Override
    public void saveCourse(CourseDTO courses, Long userId) {

        Course course = BeanMapper.map(courses, Course.class);
        course.setCreateBy(userId);
        course.setCreateAt(System.currentTimeMillis());
        course.setCourseNumber(NumberGeneratorUtil.getCourseNumber());
        courseRepository.save(course);
    }

    @Override
    @Transactional(readOnly = true)
    public CourseDTO selectCourseById(Long cid) {

        Course course = courseRepository.findById(cid).orElseThrow(() -> new BusinessException("无此信息"));
        return BeanMapper.map(course,CourseDTO.class);
    }

    @Override
    @Transactional(readOnly = true)
    public PageResp<CourseBackVO> selectCourseByPage(HomePageCourseDTO homePageCourseDTO, PageReq pageReq) {
        log.info("入参："+homePageCourseDTO);
        CourseSpecification courseSpecification = new CourseSpecification(homePageCourseDTO);
        courseSpecification.setBackOrnot(true);
        Page<Course> page = courseRepository.findAll(courseSpecification,pageReq.toPageable());
        List<Course> courses = page.getContent();
        if(CollectionUtils.isEmpty(courses)){
            return  new PageResp(page);
        }
        List<CourseBackVO> summaryVOList = BeanMapper.mapList(courses, CourseBackVO.class);
        Set<Long> categoryCodes = courses.stream().map(Course::getCategory).collect(Collectors.toSet());
        List<NavigationItem> navigationItems = naviItemRepository.findAllByCodeIn(categoryCodes);
        Map<Long, NavigationItem> navigationItemMap = navigationItems.stream().collect(Collectors.toMap(NavigationItem::getCode, obj -> obj));
        summaryVOList.forEach(responseDto -> {
            NavigationItem navigationItem = navigationItemMap.get(responseDto.getCategory());
            if(navigationItem != null){
                responseDto.setCategoryVal(navigationItem.getValue());
            }
        });

        log.info(""+summaryVOList);

        return new PageResp<>(page,summaryVOList);
    }

    @Override
    public void updateCourse(CourseDTO courses,Long userId) {
        Course courseFromDB = courseRepository.findById(courses.getId()).orElseThrow(() -> new UnacceptableException("操作的对象不存在"));
        BeanMapper.copy(courses,courseFromDB);
        //  Course course = BeanMapper.map(courses, Course.class);
        courseFromDB.setUpdateAt(System.currentTimeMillis());
        courseFromDB.setUpdateBy(userId);
        courseRepository.save(courseFromDB);
    }

    @Override
    public void deleteCourse(Long cid) {

        courseRepository.deleteById(cid);
    }

    public int deleteCourses(List<Long> cids, Integer deleted) {

       return courseRepository.updateCoursesDeletedByIds(DeletedEnum.YES.getCode(),cids);
    }

    // 0：上架；1：下架  2.删除
    @Override
    public int changeState(List<Long> cids,Integer state) throws UnacceptableException{

        if(Objects.equals(state,CourseStatusEnum.DOWN.getCourseStatus())){
            List<Course> courses = courseRepository.findAllByDeletedEqualsAndIdIn(DeletedEnum.NO.getCode(), cids);
            log.info("查询结果："+courses);
            if(!CollectionUtils.isEmpty(courses)){
                List<Course> courseList = courses.stream().sorted(Comparator.comparing(Course::getRecommend).reversed()).collect(Collectors.toList());
                Course course = courseList.get(0);
                if(Objects.equals(course.getRecommend(),YesNoEnum.YES.getCode())){
                    throw new UnacceptableException("已推荐课程不支持取消发布");
                }
            }
        }
      return   courseRepository.updateCoursesByIds(state,cids);
    }
    // 0：取消推荐；1：推荐
    public int recommendCourse(List<Long> cids,Integer recommend)throws UnacceptableException {
        // 判断要操作的课程中的发布状态
        List<Course> courses = courseRepository.findAllByDeletedEqualsAndIdIn(DeletedEnum.NO.getCode(), cids);
        log.info("查询结果："+courses);

        if(!CollectionUtils.isEmpty(courses)){
            List<Course> collectSorted = courses.stream().sorted(Comparator.comparing(Course::getStatus).reversed()).collect(Collectors.toList());
            //courses.sort(Comparator.comparing(Course::getStatus).reversed());
            log.info("排序后："+collectSorted);
            Course course = collectSorted.get(0);
            if(Objects.equals(course.getStatus(),CourseStatusEnum.DOWN.getCourseStatus())){
                if(Objects.equals(recommend,YesNoEnum.YES.getCode())){
                    throw new UnacceptableException("未发布的课程不支持推荐");
                }else if(Objects.equals(recommend,YesNoEnum.NO.getCode())){
                    throw new UnacceptableException("未发布的课程不支持取消推荐");
                }else {
                    throw new UnacceptableException("入参错误");
                }
            }
        }

        List<Course> courseList = courseRepository.findAllByStatusAndRecommendAndDeleted(CourseStatusEnum.NORMAL.getCourseStatus(), YesNoEnum.YES.getCode(),DeletedEnum.NO.getCode());

        //如果是推荐操作
        if(Objects.equals(recommend,YesNoEnum.YES.getCode())){
            if(!CollectionUtils.isEmpty(courseList)){
                Set<Long> cidsFromDb = courseList.stream().map(Course::getId).collect(Collectors.toSet());
                cidsFromDb.addAll(cids);
                // 已经推荐的课程，加上即将推荐的课程，如果超过20个
                if(cidsFromDb.size()>20){
                    throw new UnacceptableException("推荐课程数量将超过限制，请重新选择");
                }
            }
        }

        return   courseRepository.updateCoursesRecommendByIds(recommend,cids);
    }
}
